Skip to content

fix: use the correct index max_local threshold, not table's - #613

Merged
iheitlager merged 2 commits into
mainfrom
feat/req7-btree-overflow-index-key-fixture
Aug 27, 2026
Merged

fix: use the correct index max_local threshold, not table's#613
iheitlager merged 2 commits into
mainfrom
feat/req7-btree-overflow-index-key-fixture

Conversation

@iheitlager

Copy link
Copy Markdown
Member

Summary

  • 006-btree Req 7 documented a real coverage gap: no fixture exercised an overflowing index key. Adding one (overflow_index_key.db, an ~8000-byte indexed TEXT key against a 4096-byte page) immediately hit PayloadTooShort — the gap was hiding an actual bug, not just missing coverage.
  • local_payload_size computed max_local as usable_size - 35 unconditionally, but SQLite defines a smaller max_local for index cells (leaf AND interior) than for table leaf cells: (usable_size - 12) * 64 / 255 - 23 vs usable_size - 35. Every index cell whose payload landed between the two thresholds was read with a local_size far larger than what SQLite actually reserved on the page.
  • Fixing the threshold surfaced a second latent bug: index entry delete (src/btree/index/delete.rs) never freed a removed entry's overflow chain at all (table delete already does). Index entries essentially never overflowed under the old, too-generous threshold, so the gap was never exercised. Added free_overflow_chain, wired into both delete_from_leaf and the interior-match outright-delete path (remove_entry_by_child).

Test plan

  • New corpus test overflowing_index_key_reassembles_byte_identical_to_oracle against the new fixture
  • New regression test deleting_an_entry_with_overflow_frees_its_overflow_chain
  • Pre-existing deleting_all_entries_orphans_no_page (which started failing once the threshold was corrected, exposing the orphaned-overflow-page bug) now passes
  • cargo test --lib (925 tests), full corpus suite (373 tests, including fixture-regeneration reproducibility), clippy, make assurance (006-btree 18/18, no dead links) all clean

spend: ~2x the trivial fixture-generation estimate — the fixture work surfaced two real correctness bugs (wrong max_local, leaked index overflow chains on delete) that needed fixing, not just a missing fixture.

🤖 Generated with Claude Code

@iheitlager
iheitlager force-pushed the feat/req7-btree-overflow-index-key-fixture branch from 4b97e2e to 7785626 Compare August 27, 2026 21:04
local_payload_size computed max_local as usable_size - 35
unconditionally, but SQLite defines a smaller max_local for index
cells (leaf AND interior) than for table leaf cells:
(usable_size - 12) * 64 / 255 - 23 vs usable_size - 35. Every index
cell whose payload landed between the two thresholds was read with a
local_size far larger than what SQLite actually reserved on the page.

Found while closing 006-btree Req 7's documented coverage gap: adding
overflow_index_key.db (an ~8000-byte indexed TEXT key) immediately hit
PayloadTooShort, since the payload cleared the correct (smaller) index
threshold while staying under the wrong (larger) table one that had
been masking the bug.

Fixing the threshold surfaced a second latent bug: index delete
(src/btree/index/delete.rs) never freed a removed entry's overflow
chain at all (table delete already does). Index entries essentially
never overflowed under the old, too-generous threshold, so the gap
was never exercised. Added free_overflow_chain there, wired into both
delete_from_leaf and the interior-match outright-delete path
(remove_entry_by_child).

spend: ~2x the trivial fixture-generation estimate — the fixture work
surfaced two real correctness bugs (wrong max_local, leaked index
overflow chains on delete) that needed fixing, not just a missing
fixture.
@iheitlager
iheitlager force-pushed the feat/req7-btree-overflow-index-key-fixture branch from 7785626 to 8221349 Compare August 27, 2026 21:06
@iheitlager
iheitlager merged commit 3acfdc3 into main Aug 27, 2026
5 checks passed
@iheitlager
iheitlager deleted the feat/req7-btree-overflow-index-key-fixture branch August 27, 2026 21:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant